#include "camera.h"
#include <signal.h>
#include <time.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>


//=======================================================================================================
//结构体定义
//=======================================================================================================
static SAMPLE_VENC_GETSTREAM_PARA_S gs_stPara;
static pthread_t gs_VencPid;
HI_U32 sensorId;
int framew = 0;
int frameh = 0;


//=======================================================================================================
//获取图片并编码JPEG
//=======================================================================================================
HI_S32 mppVencJpeg(VENC_CHN VencChn, HI_U32 SnapCnt,char *path)
{
    struct timeval TimeoutVal;
    fd_set read_fds;
    HI_S32 s32VencFd;
    VENC_CHN_STATUS_S stStat;
    VENC_STREAM_S stStream;
    HI_S32 s32Ret;
    HI_U32 i;
    s32VencFd = HI_MPI_VENC_GetFd(VencChn);
    if (s32VencFd < 0)
    {
        SAMPLE_PRT("HI_MPI_VENC_GetFd faild with%#x!\n", s32VencFd);
        return HI_FAILURE;
    }
    for(i=0; i<SnapCnt; i++)
    {
        FD_ZERO(&read_fds);
        FD_SET(s32VencFd, &read_fds);
        TimeoutVal.tv_sec  = 1;
        TimeoutVal.tv_usec = 0;
        s32Ret = select(s32VencFd + 1, &read_fds, NULL, NULL, &TimeoutVal);//获取VENC通道里的数据，超时了一般就是没有数据
        if (s32Ret < 0)
        {
            SAMPLE_PRT("snap select failed!\n");
            return HI_FAILURE;
        }
        else if (0 == s32Ret)
        {
            SAMPLE_PRT("snap time out!\n");
            return HI_FAILURE;
        }
        else
        {
            if (FD_ISSET(s32VencFd, &read_fds))
            {
                s32Ret = HI_MPI_VENC_QueryStatus(VencChn, &stStat);//获取VENC状态
                if (s32Ret != HI_SUCCESS)
                {
                    SAMPLE_PRT("HI_MPI_VENC_QueryStatus failed with %#x!\n", s32Ret);
                    return HI_FAILURE;
                }
                if (0 == stStat.u32CurPacks)
                {
                    SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                    return HI_SUCCESS;
                }
                stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);//开辟空间留给数据流
                if (NULL == stStream.pstPack)
                {
                    SAMPLE_PRT("malloc memory failed!\n");
                    return HI_FAILURE;
                }
                stStream.u32PackCount = stStat.u32CurPacks;
                s32Ret = HI_MPI_VENC_GetStream(VencChn, &stStream, -1);//获取数据流
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", s32Ret);
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    return HI_FAILURE;
                }
                char acFile[FILE_NAME_LEN]    = {0};
                FILE* pFile;
                time_t rawtime;
                struct tm *info;
                time( &rawtime );
                info = localtime( &rawtime );
                snprintf(acFile, FILE_NAME_LEN, "%s/%d-%02d-%02d-%02d-%02d-%02d.jpg", path,
                1900+ info->tm_year,info->tm_mon+1,info->tm_mday,
                info->tm_hour,info->tm_min,info->tm_sec);
                pFile = fopen(acFile, "wb");
                if (pFile == NULL)
                {
                    SAMPLE_PRT("open file err\n");
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    return HI_FAILURE;
                }
                //把数据流写入jpeg文件里
                for (i = 0; i < stStream.u32PackCount; i++)
                {
                    fwrite(stStream.pstPack[i].pu8Addr + stStream.pstPack[i].u32Offset,
                           stStream.pstPack[i].u32Len - stStream.pstPack[i].u32Offset, 1, pFile);
                    fflush(pFile);
                }
                fclose(pFile);
                s32Ret = HI_MPI_VENC_ReleaseStream(VencChn, &stStream);//最后一定要释放数据流
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed with %#x!\n", s32Ret);
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    return HI_FAILURE;
                }
                free(stStream.pstPack);
                stStream.pstPack = NULL;
            }
        }
    }
    return HI_SUCCESS;
}

//=======================================================================================================
//用ffmpeg来编码视频流
//=======================================================================================================
HI_VOID* ffmpegEncodeFile(HI_VOID* p)
{
	HI_S32 s32Ret;
    avi_t *out_fd = NULL;
	SAMPLE_VENC_GETSTREAM_PARA_S* pstPara;
    struct timeval TimeoutVal;
    fd_set read_fds;
    HI_S32 VencFd;
    HI_CHAR aszMp4Name[64];
    VENC_CHN_STATUS_S stStat;
    VENC_STREAM_S stStream;
    //echo 3 > /proc/sys/vm/drop_caches
    time_t rawtime;
    struct tm *info;
    int i;
    pstPara = (SAMPLE_VENC_GETSTREAM_PARA_S*)p; //通过输入来获取视频的参数
    time( &rawtime );
    info = localtime( &rawtime );
    //snprintf(aszFileName,64, "%s/%d-%02d-%02d-%02d-%02d-%02d%s",gs_stPara.path,
    //1900+ info->tm_year,info->tm_mon+1,info->tm_mday,
    //info->tm_hour,info->tm_min,info->tm_sec,".h265");
    snprintf(aszMp4Name,64, "%s/%d-%02d-%02d-%02d-%02d-%02d%s",gs_stPara.path,
    1900+info->tm_year,info->tm_mon+1,info->tm_mday,
    info->tm_hour,info->tm_min,info->tm_sec,".avi");
    //pFile = fopen(aszFileName, "wb");
    out_fd = AVI_open_output_file(aszMp4Name);
    AVI_set_video(out_fd, pstPara->width, pstPara->height, 25, "hev1");
    //录下的视频播放失败一般就是这里avi的长宽设置错了，或者解码视频的长宽不对
    VencFd = HI_MPI_VENC_GetFd(0);
    while (HI_TRUE == pstPara->bThreadStart)
    {
        FD_ZERO(&read_fds);
        FD_SET(VencFd, &read_fds);
        TimeoutVal.tv_sec  = 2;
        TimeoutVal.tv_usec = 0;
        s32Ret = select(VencFd + 1, &read_fds, NULL, NULL, &TimeoutVal);
        if (s32Ret > 0)
        {
            memset(&stStream, 0, sizeof(stStream));
            s32Ret = HI_MPI_VENC_QueryStatus(0, &stStat);//获取视频流和获取图片的过程一样
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VENC_QueryStatus chn[] failed with %#x!\n", s32Ret);
                break;
            }
            if(0 == stStat.u32CurPacks)
            {
                  SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                  continue;
            }
            stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
            if (NULL == stStream.pstPack)
            {
                SAMPLE_PRT("malloc stream pack failed!\n");
                break;
            }
            stStream.u32PackCount = stStat.u32CurPacks;
            s32Ret = HI_MPI_VENC_GetStream(0, &stStream, HI_TRUE);
            if (HI_SUCCESS != s32Ret)
            {
                free(stStream.pstPack);
                stStream.pstPack = NULL;
                SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", \
                           s32Ret);
                break;
            }
            #if 1
            for (i = 0; i < stStream.u32PackCount; i++)
            {
                AVI_write_frame(out_fd, (char *)(stStream.pstPack[i].pu8Addr + stStream.pstPack[i].u32Offset),
                stStream.pstPack[i].u32Len - stStream.pstPack[i].u32Offset);
            }
            #endif
            s32Ret = HI_MPI_VENC_ReleaseStream(0, &stStream);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed!\n");
                free(stStream.pstPack);
                stStream.pstPack = NULL;
                break;
            }
            free(stStream.pstPack);
            stStream.pstPack = NULL;
        }
    }
    AVI_close(out_fd);

}


//=======================================================================================================
//  VENC 视频及图片编码
//=======================================================================================================
HI_S32 mppVencStart(PAYLOAD_TYPE_E enType,SIZE_S stSize,HI_U32 u32FrameRate,VPSS_CHN VpssChn, VENC_CHN VencChn,
                    HI_U32 u32Profile, HI_BOOL bRcnRefShareBuf,VENC_GOP_ATTR_S *pstGopAttr,char *path)
{
    VENC_RECV_PIC_PARAM_S  stRecvParam;
    VENC_CHN_ATTR_S        stVencChnAttr;
    VENC_ATTR_JPEG_S       stJpegAttr;
    VENC_H265_FIXQP_S      stH265FixQp;
    VENC_MJPEG_FIXQP_S     stMjpegeFixQp;
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;
    /******************************************
     step 1:  Create Venc Channel
    ******************************************/
    stVencChnAttr.stVencAttr.enType          = enType;
    stVencChnAttr.stVencAttr.u32MaxPicWidth  = stSize.u32Width;
    stVencChnAttr.stVencAttr.u32MaxPicHeight = stSize.u32Height;
    stVencChnAttr.stVencAttr.u32PicWidth     = stSize.u32Width;/*the picture width*/
    stVencChnAttr.stVencAttr.u32PicHeight    = stSize.u32Height;/*the picture height*/
    stVencChnAttr.stVencAttr.u32BufSize      = stSize.u32Width * stSize.u32Height * 2;/*stream buffer size*/
    stVencChnAttr.stVencAttr.u32Profile      = u32Profile;
    stVencChnAttr.stVencAttr.bByFrame        = HI_TRUE;/*get stream mode is slice mode or frame mode?*/
    switch (enType)
    {
        case PT_H265://H265视频的参数设置
            stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265FIXQP;
            stH265FixQp.u32Gop              = 30;
            stH265FixQp.u32SrcFrameRate     = u32FrameRate;
            stH265FixQp.fr32DstFrameRate    = u32FrameRate;
            stH265FixQp.u32IQp              = 25;
            stH265FixQp.u32PQp              = 30;
            stH265FixQp.u32BQp              = 32;
            memcpy(&stVencChnAttr.stRcAttr.stH265FixQp, &stH265FixQp, sizeof(VENC_H265_FIXQP_S));
            stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
            memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
        break;
        case PT_MJPEG://MJPEG的参数设置，目前没用
            stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_MJPEGFIXQP;
            stMjpegeFixQp.u32Qfactor        = 95;
            stMjpegeFixQp.u32SrcFrameRate    = u32FrameRate;
            stMjpegeFixQp.fr32DstFrameRate   = u32FrameRate;
            memcpy(&stVencChnAttr.stRcAttr.stMjpegFixQp, &stMjpegeFixQp,sizeof(VENC_MJPEG_FIXQP_S));
            stVencChnAttr.stGopAttr.enGopMode  = VENC_GOPMODE_NORMALP;
            stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta = 0;
        break;
        case PT_JPEG://JPEG的参数设置
            stJpegAttr.bSupportDCF     = HI_FALSE;
            stJpegAttr.stMPFCfg.u8LargeThumbNailNum = 0;
            stJpegAttr.enReceiveMode                = VENC_PIC_RECEIVE_SINGLE;
            memcpy(&stVencChnAttr.stVencAttr.stAttrJpege, &stJpegAttr, sizeof(VENC_ATTR_JPEG_S));
            stVencChnAttr.stGopAttr.enGopMode  = VENC_GOPMODE_NORMALP;
            stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta = 0;
        break;
        default:
        break;
    }
    CHECK_RET(HI_MPI_VENC_CreateChn(VencChn, &stVencChnAttr), "HI_MPI_VENC_CreateChn()");
    stRecvParam.s32RecvPicNum = -1;
    CHECK_RET(HI_MPI_VENC_StartRecvFrame(VencChn,&stRecvParam), "HI_MPI_VENC_StartRecvFrame()");
    stSrcChn.enModId   = HI_ID_VPSS;
    stSrcChn.s32DevId = 0;
    stSrcChn.s32ChnId  = VpssChn;
    stDestChn.enModId  = HI_ID_VENC;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = VencChn;
    CHECK_RET(HI_MPI_SYS_Bind(&stSrcChn, &stDestChn), "HI_MPI_SYS_Bind(VPSS-VENC)");
    switch(enType)
    {
        case PT_H265:
            gs_stPara.bThreadStart = HI_TRUE;
            gs_stPara.s32Cnt = 1;
            gs_stPara.VeChn[0] = 0;
            memset(gs_stPara.path,0,50);
            memcpy(gs_stPara.path,path,strlen(path));//设置路径
            gs_stPara.width = stSize.u32Width;
            gs_stPara.height = stSize.u32Height;
            pthread_create(&gs_VencPid, 0, ffmpegEncodeFile, (HI_VOID*)&gs_stPara);//开启录像进程
        break;
        case PT_JPEG:
            mppVencJpeg(0, 1,path);
        break;
        default:
        break;
    }
    return HI_SUCCESS;
}


#if 0
//=======================================================================================================
// 编码测试,
//=======================================================================================================
HI_S32 mppVencStart(PAYLOAD_TYPE_E enType,SIZE_S stSize,HI_U32 u32FrameRate,VPSS_CHN VpssChn, VENC_CHN VencChn, 
                    HI_U32 u32Profile, HI_BOOL bRcnRefShareBuf,VENC_GOP_ATTR_S *pstGopAttr,char *path)
{
    VENC_RECV_PIC_PARAM_S  stRecvParam;
    VENC_CHN_ATTR_S        stVencChnAttr;
    VENC_ATTR_JPEG_S       stJpegAttr;
    VENC_H265_FIXQP_S      stH265FixQp;
    VENC_MJPEG_FIXQP_S     stMjpegeFixQp;
    MPP_CHN_S              stSrcChn;
    MPP_CHN_S              stDestChn;

    HI_U32                 u32StatTime  = 1;
    HI_U32                 u32Gop       = 30;   // gop 值。取值范围： [1, 65536]
    SAMPLE_RC_E            enRcMode;     

    /******************************************
     step 1:  Create Venc Channel
    ******************************************/
    stVencChnAttr.stVencAttr.enType          = enType;
    stVencChnAttr.stVencAttr.u32MaxPicWidth  = stSize.u32Width;
    stVencChnAttr.stVencAttr.u32MaxPicHeight = stSize.u32Height;
    stVencChnAttr.stVencAttr.u32PicWidth     = stSize.u32Width;                                 //the picture width
    stVencChnAttr.stVencAttr.u32PicHeight    = stSize.u32Height;                                //the picture height
    stVencChnAttr.stVencAttr.u32BufSize      = stSize.u32Width * stSize.u32Height * 2;          //stream buffer size
    stVencChnAttr.stVencAttr.u32Profile      = u32Profile;
    stVencChnAttr.stVencAttr.bByFrame        = HI_TRUE;
    
    switch (enType)
    {
        //--------------------------------------------------------------------------------------------------------------------
        //    H265
        //--------------------------------------------------------------------------------------------------------------------
        case PT_H265://H265视频的参数设置
        {

            enRcMode = SAMPLE_RC_FIXQP;         //改变此参数以确定不同的 H265 编码模式,

            if (SAMPLE_RC_CBR == enRcMode)
            {
                VENC_H265_CBR_S    stH265Cbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR;
                stH265Cbr.u32Gop                = u32Gop;
                stH265Cbr.u32StatTime           = u32StatTime;      //stream rate statics time(s) 
                stH265Cbr.u32SrcFrameRate       = u32FrameRate;     //input (vi) frame rate 
                stH265Cbr.fr32DstFrameRate      = u32FrameRate;     //target frame rate 

                //stH265Cbr.u32BitRate          = 1024 * 2 + 2048*u32FrameRate/30;      //设置码率 1080P               
                stH265Cbr.u32BitRate            = 1024 * 15+ 2048*u32FrameRate/30;      //default
                //stH265Cbr.u32BitRate          = 1024 * 2 + 1024*u32FrameRate/30;      //PIC_720P
                //stH265Cbr.u32BitRate          = 1024 * 2 + 2048*u32FrameRate/30;      //PIC_1080P
                //stH265Cbr.u32BitRate          = 1024 * 3 + 3072*u32FrameRate/30;      //PIC_2592x1944
                //stH265Cbr.u32BitRate          = 1024 * 5 + 5120*u32FrameRate/30;      //PIC_3840x2160

                memcpy(&stVencChnAttr.stRcAttr.stH265Cbr, &stH265Cbr, sizeof(VENC_H265_CBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if (SAMPLE_RC_FIXQP == enRcMode)
            {
                VENC_H265_FIXQP_S    stH265FixQp;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265FIXQP;
                stH265FixQp.u32Gop              = 30;
                stH265FixQp.u32SrcFrameRate     = u32FrameRate;
                stH265FixQp.fr32DstFrameRate    = u32FrameRate;
                stH265FixQp.u32IQp              = 25;
                stH265FixQp.u32PQp              = 30;
                stH265FixQp.u32BQp              = 32;

                memcpy(&stVencChnAttr.stRcAttr.stH265FixQp, &stH265FixQp, sizeof(VENC_H265_FIXQP_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if (SAMPLE_RC_VBR == enRcMode)
            {
                VENC_H265_VBR_S    stH265Vbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265VBR;
                stH265Vbr.u32Gop                = u32Gop;
                stH265Vbr.u32StatTime           = u32StatTime;
                stH265Vbr.u32SrcFrameRate       = u32FrameRate;
                stH265Vbr.fr32DstFrameRate      = u32FrameRate;

                //stH265Vbr.u32MaxBitRate       = 1024 * 2 + 2048*u32FrameRate/30;      //设置码率 1080P   
                stH265Vbr.u32MaxBitRate         = 1024 * 15+ 2048*u32FrameRate/30;      //default

                memcpy(&stVencChnAttr.stRcAttr.stH265Vbr, &stH265Vbr, sizeof(VENC_H265_VBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if(SAMPLE_RC_AVBR == enRcMode)
            {
                VENC_H265_AVBR_S    stH265AVbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265AVBR;
                stH265AVbr.u32Gop               = u32Gop;
                stH265AVbr.u32StatTime          = u32StatTime;
                stH265AVbr.u32SrcFrameRate      = u32FrameRate;
                stH265AVbr.fr32DstFrameRate     = u32FrameRate;

                //stH265AVbr.u32MaxBitRate        = 1024 * 2 + 2048*u32FrameRate/30;    //设置码率 1080P  
                stH265AVbr.u32MaxBitRate        = 1024 * 15+ 2048*u32FrameRate/30;      //default

                memcpy(&stVencChnAttr.stRcAttr.stH265AVbr, &stH265AVbr, sizeof(VENC_H265_AVBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if(SAMPLE_RC_QVBR == enRcMode)
            {
                VENC_H265_QVBR_S    stH265QVbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265QVBR;
                stH265QVbr.u32Gop               = u32Gop;
                stH265QVbr.u32StatTime          = u32StatTime;
                stH265QVbr.u32SrcFrameRate      = u32FrameRate;
                stH265QVbr.fr32DstFrameRate     = u32FrameRate;

                //stH265QVbr.u32TargetBitRate   = 1024 * 2 + 2048*u32FrameRate/30;      //设置码率 1080P 
                stH265QVbr.u32TargetBitRate     = 1024 * 15+ 2048*u32FrameRate/30;      //default

                memcpy(&stVencChnAttr.stRcAttr.stH265QVbr, &stH265QVbr, sizeof(VENC_H265_QVBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if(SAMPLE_RC_CVBR == enRcMode)
            {
                VENC_H265_CVBR_S    stH265CVbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CVBR;
                stH265CVbr.u32Gop               = u32Gop;
                stH265CVbr.u32StatTime          = u32StatTime;
                stH265CVbr.u32SrcFrameRate      = u32FrameRate;
                stH265CVbr.fr32DstFrameRate     = u32FrameRate;
                stH265CVbr.u32LongTermStatTime  = 1;
                stH265CVbr.u32ShortTermStatTime = u32StatTime;

                stH265CVbr.u32MaxBitRate         = 1024 * 24  + 5120*u32FrameRate/30;
                stH265CVbr.u32LongTermMaxBitrate = 1024 * 15  + 2048*u32FrameRate/30;
                stH265CVbr.u32LongTermMinBitrate = 1024*5;                                  //default

                //stH265CVbr.u32MaxBitRate         = 1024 * 2 + 2048*u32FrameRate/30;
                //stH265CVbr.u32LongTermMaxBitrate = 1024 * 2 + 2048*u32FrameRate/30;
                //stH265CVbr.u32LongTermMinBitrate = 1024;                                  //1080P

                //stH265CVbr.u32MaxBitRate         = 1024 * 4 + 3072*u32FrameRate/30;
                //stH265CVbr.u32LongTermMaxBitrate = 1024 * 3 + 3072*u32FrameRate/30;
                //stH265CVbr.u32LongTermMinBitrate = 1024*2;                                //PIC_2592x1944

                //stH265CVbr.u32MaxBitRate         = 1024 * 8  + 5120*u32FrameRate/30;
                //stH265CVbr.u32LongTermMaxBitrate = 1024 * 5  + 5120*u32FrameRate/30;
                //stH265CVbr.u32LongTermMinBitrate = 1024*3;                                //PIC_3840x2160              

                memcpy(&stVencChnAttr.stRcAttr.stH265CVbr, &stH265CVbr, sizeof(VENC_H265_CVBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if(SAMPLE_RC_QPMAP == enRcMode)
            {
                VENC_H265_QPMAP_S    stH265QpMap;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265QPMAP;
                stH265QpMap.u32Gop           = u32Gop;
                stH265QpMap.u32StatTime      = u32StatTime;
                stH265QpMap.u32SrcFrameRate  = u32FrameRate;
                stH265QpMap.fr32DstFrameRate = u32FrameRate;
                stH265QpMap.enQpMapMode      = VENC_RC_QPMAP_MODE_MEANQP;
                memcpy(&stVencChnAttr.stRcAttr.stH265QpMap, &stH265QpMap, sizeof(VENC_H265_QPMAP_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
        }
        break;

        //--------------------------------------------------------------------------------------------------------------------
        //    H264
        //--------------------------------------------------------------------------------------------------------------------
        case PT_H264:
        {
            enRcMode = VENC_H264_VBR_S;                         //改变此参数以确定不同的 H265 编码模式,

            if (SAMPLE_RC_CBR == enRcMode)
            {
                VENC_H264_CBR_S    stH264Cbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
                stH264Cbr.u32Gop                = u32Gop; 
                stH264Cbr.u32StatTime           = u32StatTime; 
                stH264Cbr.u32SrcFrameRate       = u32FrameRate; 
                stH264Cbr.fr32DstFrameRate      = u32FrameRate; 

                //u32BitRate  输出码率 以 kbps 为单位。取值范围：[2,51200] 
                stH264Cbr.u32BitRate            = 1024 * 24  + 5120*u32FrameRate/30;  //PIC_7680x4320  8K=default   

                //stH264Cbr.u32BitRate            = 1024 * 3 + 1024*u32FrameRate/30;  //PIC_720P
                //stH264Cbr.u32BitRate            = 1024 * 2 + 2048*u32FrameRate/30;  //PIC_1080P
                //stH264Cbr.u32BitRate            = 1024 * 4 + 3072*u32FrameRate/30;  //PIC_2592x1944
                //stH264Cbr.u32BitRate            = 1024 * 8 + 5120*u32FrameRate/30;  //PIC_3840x2160      4K
                //stH264Cbr.u32BitRate            = 1024 * 24+ 5120*u32FrameRate/30;  //PIC_7680x4320      8K=default 

                memcpy(&stVencChnAttr.stRcAttr.stH264Cbr, &stH264Cbr, sizeof(VENC_H264_CBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if (SAMPLE_RC_FIXQP == enRcMode)
            {
                VENC_H264_FIXQP_S    stH264FixQp;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264FIXQP;
                stH264FixQp.u32Gop           = 30;
                stH264FixQp.u32SrcFrameRate  = u32FrameRate;
                stH264FixQp.fr32DstFrameRate = u32FrameRate;
                stH264FixQp.u32IQp           = 25;  //I 帧所有宏块 Qp 值。取值范围： [0, 51]
                stH264FixQp.u32PQp           = 30;  //P 帧所有宏块 Qp 值。取值范围： [0, 51]
                stH264FixQp.u32BQp           = 32;  //B 帧所有宏块 Qp 值。取值范围： [0, 51]
                memcpy(&stVencChnAttr.stRcAttr.stH264FixQp, &stH264FixQp, sizeof(VENC_H264_FIXQP_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if (SAMPLE_RC_VBR == enRcMode)
            {
                VENC_H264_VBR_S    stH264Vbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264VBR;
                stH264Vbr.u32Gop           = u32Gop;
                stH264Vbr.u32StatTime      = u32StatTime;
                stH264Vbr.u32SrcFrameRate  = u32FrameRate;
                stH264Vbr.fr32DstFrameRate = u32FrameRate;
                
                //u32MaxBitRate  最大码率 以 kbps 为单位。取值范围：[2,51200] 
                stH264Vbr.u32MaxBitRate    = 1024 * 15  + 2048*u32FrameRate/30;     //default

                //stH264Vbr.u32MaxBitRate = 1024 * 2   + 1024*u32FrameRate/30;      //PIC_720P  
                //stH264Vbr.u32MaxBitRate = 1024 * 2   + 2048*u32FrameRate/30;      //PIC_1080P
                //stH264Vbr.u32MaxBitRate = 1024 * 3   + 3072*u32FrameRate/30;      //PIC_2592x1944
                //stH264Vbr.u32MaxBitRate = 1024 * 5   + 5120*u32FrameRate/30;      //PIC_3840x2160    4K
                //stH264Vbr.u32MaxBitRate = 1024 * 20  + 5120*u32FrameRate/30;      //PIC_7680x4320    8K

                memcpy(&stVencChnAttr.stRcAttr.stH264Vbr, &stH264Vbr, sizeof(VENC_H264_VBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if (SAMPLE_RC_AVBR == enRcMode)
            {
                VENC_H264_AVBR_S    stH264AVbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264AVBR;
                stH264AVbr.u32Gop           = u32Gop;
                stH264AVbr.u32StatTime      = u32StatTime;
                stH264AVbr.u32SrcFrameRate  = u32FrameRate;
                stH264AVbr.fr32DstFrameRate = u32FrameRate;
 
                //u32MaxBitRate  最大码率 以 kbps 为单位。取值范围：[2,51200]
                stH264AVbr.u32MaxBitRate    = 1024 * 15  + 2048*u32FrameRate/30;     //default
                
                //stH264AVbr.u32MaxBitRate  = 1024 * 2   + 1024*u32FrameRate/30;     //PIC_720P
                //stH264AVbr.u32MaxBitRate  = 1024 * 2   + 2048*u32FrameRate/30;     //PIC_1080P
                //stH264AVbr.u32MaxBitRate  = 1024 * 3   + 3072*u32FrameRate/30;     //PIC_2592x1944
                //stH264AVbr.u32MaxBitRate  = 1024 * 5   + 5120*u32FrameRate/30;     //PIC_3840x2160
                //stH264AVbr.u32MaxBitRate  = 1024 * 20  + 5120*u32FrameRate/30;     //PIC_7680x4320

                memcpy(&stVencChnAttr.stRcAttr.stH264AVbr, &stH264AVbr, sizeof(VENC_H264_AVBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if (SAMPLE_RC_QVBR == enRcMode)
            {
                VENC_H264_QVBR_S    stH264QVbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264QVBR;
                stH264QVbr.u32Gop           = u32Gop;
                stH264QVbr.u32StatTime      = u32StatTime;
                stH264QVbr.u32SrcFrameRate  = u32FrameRate;
                stH264QVbr.fr32DstFrameRate = u32FrameRate;

                //u32MaxBitRate  最大码率 以 kbps 为单位。取值范围：[2,51200]
                stH264QVbr.u32TargetBitRate   = 1024 * 15  + 2048*u32FrameRate/30;      //default
                //stH264QVbr.u32TargetBitRate = 1024 * 2   + 1024*u32FrameRate/30;      //PIC_720P
                //stH264QVbr.u32TargetBitRate = 1024 * 2   + 2048*u32FrameRate/30;      //PIC_1080P
                //stH264QVbr.u32TargetBitRate = 1024 * 5   + 5120*u32FrameRate/30;      //PIC_3840x2160
                //stH264QVbr.u32TargetBitRate = 1024 * 20  + 5120*u32FrameRate/30;      //PIC_7680x4320

                memcpy(&stVencChnAttr.stRcAttr.stH264QVbr, &stH264QVbr, sizeof(VENC_H264_QVBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
            else if(SAMPLE_RC_CVBR == enRcMode)
            {
                VENC_H264_CVBR_S    stH264CVbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CVBR;
                stH264CVbr.u32Gop               = u32Gop;
                stH264CVbr.u32StatTime          = u32StatTime;
                stH264CVbr.u32SrcFrameRate      = u32FrameRate;
                stH264CVbr.fr32DstFrameRate     = u32FrameRate;
                stH264CVbr.u32LongTermStatTime  = 1;
                stH264CVbr.u32ShortTermStatTime = u32StatTime;
                        

                stH264CVbr.u32MaxBitRate         = 1024 * 24  + 5120*u32FrameRate/30;
                stH264CVbr.u32LongTermMaxBitrate = 1024 * 15 + 2048*u32FrameRate/30;
                stH264CVbr.u32LongTermMinBitrate = 1024*5;                                  //default

                //PIC_720P
                //stH264CVbr.u32MaxBitRate         = 1024 * 24  + 5120*u32FrameRate/30;
                //stH264CVbr.u32LongTermMaxBitrate = 1024 * 15 + 2048*u32FrameRate/30;
                //stH264CVbr.u32LongTermMinBitrate = 1024*5;                                
                
                //PIC_1080P
                //stH264CVbr.u32MaxBitRate         = 1024 * 2 + 2048*u32FrameRate/30;
                //stH264CVbr.u32LongTermMaxBitrate = 1024 * 2 + 2048*u32FrameRate/30;
                //stH264CVbr.u32LongTermMinBitrate = 1024;                                  

                //PIC_3840x2160:
                //stH264CVbr.u32MaxBitRate         = 1024 * 8  + 5120*u32FrameRate/30;
                //stH264CVbr.u32LongTermMaxBitrate = 1024 * 5  + 5120*u32FrameRate/30;
                //stH264CVbr.u32LongTermMinBitrate = 1024*3;

                //PIC_7680x4320:
                //stH264CVbr.u32MaxBitRate         = 1024 * 24  + 5120*u32FrameRate/30;
                //stH264CVbr.u32LongTermMaxBitrate = 1024 * 20 + 5120*u32FrameRate/30;
                //stH264CVbr.u32LongTermMinBitrate = 1024*6;

                memcpy(&stVencChnAttr.stRcAttr.stH264CVbr, &stH264CVbr, sizeof(VENC_H264_CVBR_S));
                stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
                memcpy(&stVencChnAttr.stGopAttr,pstGopAttr,sizeof(VENC_GOP_ATTR_S));
            }
        }
        break;


        //--------------------------------------------------------------------------------------------------------------------
        //   M-JPEG
        //--------------------------------------------------------------------------------------------------------------------
        case PT_MJPEG:
        {

            enRcMode = SAMPLE_RC_CBR;               //改变此参数以确定不同的 H265 编码模式,

            if (SAMPLE_RC_FIXQP == enRcMode)
            {
                VENC_MJPEG_FIXQP_S stMjpegeFixQp;   //固定Qp值

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_MJPEGFIXQP;
                stMjpegeFixQp.u32Qfactor        = 95;                       //Range:[1,99];image quality.
                stMjpegeFixQp.u32SrcFrameRate   = u32FrameRate;
                stMjpegeFixQp.fr32DstFrameRate  = u32FrameRate;

                memcpy(&stVencChnAttr.stRcAttr.stMjpegFixQp, &stMjpegeFixQp,sizeof(VENC_MJPEG_FIXQP_S));
                stVencChnAttr.stGopAttr.enGopMode   = VENC_GOPMODE_NORMALP;
                stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta = 0;
            }
            else if (SAMPLE_RC_CBR == enRcMode)     //CBR 恒定比特率
            {
                VENC_MJPEG_CBR_S stMjpegeCbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_MJPEGCBR;
                stMjpegeCbr.u32StatTime         = u32StatTime;
                stMjpegeCbr.u32SrcFrameRate     = u32FrameRate;
                stMjpegeCbr.fr32DstFrameRate    = u32FrameRate;

                //stMjpegeCbr.u32BitRate 平均 bitrate，以 kbps 为单位,取值范围：[2,102400]   最大100Mb=12.5MB每秒
                stMjpegeCbr.u32BitRate          = 1024 * 20 + 2048*u32FrameRate/30;     //default
                //stMjpegeCbr.u32BitRate        = 1024 * 5  + 1024*u32FrameRate/30;     //PIC_720P
                //stMjpegeCbr.u32BitRate        = 1024 * 8  + 2048*u32FrameRate/30;     //PIC_1080P
                //stMjpegeCbr.u32BitRate        = 1024 * 25 + 5120*u32FrameRate/30;     //PIC_3840x2160
                //stMjpegeCbr.u32BitRate        = 1024 * 40 + 5120*u32FrameRate/30;     //PIC_7680x4320

                memcpy(&stVencChnAttr.stRcAttr.stMjpegCbr, &stMjpegeCbr,sizeof(VENC_MJPEG_CBR_S));
                stVencChnAttr.stGopAttr.enGopMode               = VENC_GOPMODE_NORMALP;//VENC_GOPMODE_DUALP;  //VENC_GOPMODE_SMARTP;
                stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta  = 0;

            }
            else if (SAMPLE_RC_VBR == enRcMode)     //VBR 动态比特率
            {
                VENC_MJPEG_VBR_S   stMjpegVbr;

                stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_MJPEGVBR;
                stMjpegVbr.u32StatTime          = u32StatTime;          //VBR 码率统计时间， 以秒为单位。取值范围： [1, 60]。
                stMjpegVbr.u32SrcFrameRate      = u32FrameRate;         //编码器输入帧率，以 fps 为单位, 取值范围： [1, 240]
                stMjpegVbr.fr32DstFrameRate     = 5;                    //编码器输出帧率，以 fps 为单位。 取值范围： [1/64, u32SrcFrmRate]。

                //u32MaxBitRate = 最大 bitrate， 以 kbps 为单位。取值范围：[2,102400] 
                stMjpegVbr.u32MaxBitRate        = 1024 * 20 + 2048*u32FrameRate/30;         //default
                //stMjpegVbr.u32MaxBitRate      = 1024 * 5 + 1024*u32FrameRate/30;          //PIC_720P
                //stMjpegVbr.u32MaxBitRate      = 1024 * 8 + 2048*u32FrameRate/30;          //PIC_1080P
                //stMjpegVbr.u32MaxBitRate      = 1024 * 25 + 5120*u32FrameRate/30;         //PIC_3840x2160
                //stMjpegVbr.u32MaxBitRate      = 1024 * 40 + 5120*u32FrameRate/30;         //PIC_7680x4320

                memcpy(&stVencChnAttr.stRcAttr.stMjpegVbr, &stMjpegVbr,sizeof(VENC_MJPEG_VBR_S));
                stVencChnAttr.stGopAttr.enGopMode               = VENC_GOPMODE_NORMALP;//VENC_GOPMODE_DUALP;  //VENC_GOPMODE_SMARTP;
                stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta  = 0;
            }
        }
        break;

        //--------------------------------------------------------------------------------------------------------------------
        //   JPEG
        //--------------------------------------------------------------------------------------------------------------------
        case PT_JPEG:
            stJpegAttr.bSupportDCF                              = HI_FALSE;
            stJpegAttr.stMPFCfg.u8LargeThumbNailNum             = 0;
            stJpegAttr.enReceiveMode                            = VENC_PIC_RECEIVE_SINGLE;
            memcpy(&stVencChnAttr.stVencAttr.stAttrJpege, &stJpegAttr, sizeof(VENC_ATTR_JPEG_S));
            stVencChnAttr.stGopAttr.enGopMode                   = VENC_GOPMODE_NORMALP;//VENC_GOPMODE_DUALP;  //VENC_GOPMODE_SMARTP;
            stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta      = 0;
            break;

        default:
            break;
    }

    CHECK_RET(HI_MPI_VENC_CreateChn(VencChn, &stVencChnAttr), "HI_MPI_VENC_CreateChn()");
    stRecvParam.s32RecvPicNum = -1;
    CHECK_RET(HI_MPI_VENC_StartRecvFrame(VencChn,&stRecvParam), "HI_MPI_VENC_StartRecvFrame()");
    stSrcChn.enModId    = HI_ID_VPSS;
    stSrcChn.s32DevId   = 0;
    stSrcChn.s32ChnId   = VpssChn;
    stDestChn.enModId   = HI_ID_VENC;
    stDestChn.s32DevId  = 0;
    stDestChn.s32ChnId  = VencChn;
    CHECK_RET(HI_MPI_SYS_Bind(&stSrcChn, &stDestChn), "HI_MPI_SYS_Bind(VPSS-VENC)");
    switch(enType)
    {
        case PT_H265:
            gs_stPara.bThreadStart = HI_TRUE;
            gs_stPara.s32Cnt = 1;
            gs_stPara.VeChn[0] = 0;
            memset(gs_stPara.path,0,50);
            memcpy(gs_stPara.path,path,strlen(path));//设置路径
            gs_stPara.width = stSize.u32Width;
            gs_stPara.height = stSize.u32Height;
            pthread_create(&gs_VencPid, 0, ffmpegEncodeFile, (HI_VOID*)&gs_stPara);//开启录像进程
        break;
        case PT_JPEG:
            mppVencJpeg(0, 1,path);
        break;
        default:
        break;
    }
    return HI_SUCCESS;
}
#endif

//=======================================================================================================
//停止VENC的功能
//=======================================================================================================
HI_S32 mppVencStop(VPSS_CHN VpssChn)
{
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;
    if (HI_TRUE == gs_stPara.bThreadStart)
    {
        gs_stPara.bThreadStart = HI_FALSE;
        pthread_join(gs_VencPid, 0);
    }
    stSrcChn.enModId   = HI_ID_VPSS;
    stSrcChn.s32DevId  = 0;
    stSrcChn.s32ChnId  = VpssChn;
    stDestChn.enModId  = HI_ID_VENC;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = 0;
    CHECK_RET(HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn), "HI_MPI_SYS_UnBind(VPSS-VENC)");
    CHECK_RET(HI_MPI_VENC_StopRecvFrame(0), "HI_MPI_VENC_StopRecvFrame()");
    CHECK_RET(HI_MPI_VENC_DestroyChn(0), "HI_MPI_VENC_DestroyChn()");
    return HI_SUCCESS;
}


//=======================================================================================================
//解码视频文件avi，使其变成H265文件可以直接播放
//=======================================================================================================
int mppVdecDecode(char *filename)
{
    char * vidbuf = (char *)malloc(327680);
    avi_t *avifile;
    int frame;
    int frames;
    FILE* pFile;
    avifile = AVI_open_input_file(filename, 1); //打开源文件
    if(avifile == NULL)
    {
        printf("open error \n");
        return -1;
    }
    frames = AVI_video_frames(avifile);
    framew = AVI_video_width(avifile);//获取视频长宽
    frameh = AVI_video_height(avifile);
    pFile = fopen(h265Path, "wb");
    decodeFrame = 0;
    totalFrame = frames;
    decodeFlag = 1;
    printf("w:%d,h:%d,frames:%d,file:%s\n",framew,frameh,frames,h265Path);
    AVI_seek_start( avifile ); //寻找文件开始
    for (frame = 0; frame < frames;frame++)//read and write avi per fream
    {
        decodeFrame = frame;
        AVI_set_video_position(avifile, frame);//将avi文件移动到第fream帧
        AVI_read_frame(avifile,(char *)vidbuf);//read fream set video into vidbuf
        fwrite(vidbuf,AVI_frame_size(avifile, frame), 1, pFile);
        fflush(pFile);
    }
    AVI_close(avifile);
    fclose(pFile);
    decodeFlag = 0;
    return 0;
}


